package com.xxj.duck;

import java.io.IOException;
import java.util.Locale;

import org.anddev.andengine.audio.music.Music;
import org.anddev.andengine.audio.music.MusicFactory;
import org.anddev.andengine.audio.sound.Sound;
import org.anddev.andengine.audio.sound.SoundFactory;
import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.handler.IUpdateHandler;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.Scene.IOnSceneTouchListener;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.font.Font;
import org.anddev.andengine.opengl.font.FontFactory;
import org.anddev.andengine.opengl.texture.Texture;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.opengl.texture.region.TextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
import org.anddev.andengine.sensor.accelerometer.AccelerometerData;
import org.anddev.andengine.sensor.accelerometer.IAccelerometerListener;
import org.anddev.andengine.ui.activity.LayoutGameActivity;
import org.anddev.andengine.util.Debug;

import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.xxj.duck.core.Game;
import com.xxj.duck.ui.GameScore;

/*
 Execute order as below:
 onCreate() ...
 onLoadEngine() ...
 getLayoutID() ... 
 getRenderSurfaceViewID() ...  
 onResume() ...  
 onLoadResources() ... 
 onLoadScene() ...
 onLoadComplete() ...
 */
public class DuckGame extends LayoutGameActivity implements
		IAccelerometerListener {

	public static int WIDTH;
	public static int HEIGHT;

	public static TextureRegion hills;
	public static TextureRegion sky;
	public static TextureRegion largeCloud;
	public static TextureRegion mediumCloud;
	public static TextureRegion smallCloud;
	public static TextureRegion grass;
	public static TextureRegion aim;
	public static TextureRegion barrel;
	public static TextureRegion feather;
	public static TextureRegion featherFlipped;
	public static TextureRegion shell;
	public static TextureRegion flash;
	public static TextureRegion shot;
	public static TextureRegion logo;

	public static TextureRegion pauseButton;
	public static TextureRegion startButton;
	public static TextureRegion settingsButton;
	public static TextureRegion scoresButton;

	public static TiledTextureRegion duckFly;
	public static TiledTextureRegion duckFlyFlipped;

	public static Sound sGroundHit;
	public static Sound sDuckQuack;
	public static Sound sShotReload;

	public static Music music;

	public static Font font;
	public static Texture fontTexture;

	private Game game;
	private boolean musicPaused;

	public static final String SP_PREFS_NAME = "GAME_SETTINGS";
	public static final String SP_USE_SOUND = "SOUND";
	public static final String SP_USE_VIBRO = "VIBRO";

	public GameScore gameScore;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		Log.d(" xx ", "onCreate() ...");
		super.onCreate(savedInstanceState);
		this.initButtons();
		gameScore = new GameScore(this);
		new Thread(new AdManager(this), " >> AD thread << ").start();
	}

	private void initButtons() {

		final LinearLayout saveScoresLayout = (LinearLayout) findViewById(R.id.saveScoreDialog);
		final LinearLayout restartLayout = (LinearLayout) findViewById(R.id.restartDialog);

		TextView scoreTextCtrl = (TextView) saveScoresLayout
				.findViewById(R.id.scoreText);
		scoreTextCtrl.setText(this.getResources().getString(
				R.string.wish_to_save_scores)
				+ "(" + 0 + ")");

		Button btnSubmit = (Button) saveScoresLayout
				.findViewById(R.id.submitButton);
		btnSubmit.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				if (gameScore.submitScore(game.getScore())) {
					saveScoresLayout.setVisibility(View.GONE);
					restartLayout.setVisibility(View.VISIBLE);
				}
			}
		});

		Button btnSkip = (Button) saveScoresLayout.findViewById(R.id.skipButton);
		btnSkip.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				saveScoresLayout.setVisibility(View.GONE);
				restartLayout.setVisibility(View.VISIBLE);
			}
		});

		Button btnRestart = (Button) restartLayout.findViewById(R.id.replayBtn);
		btnRestart.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				onGameResumed();
				if (game != null) {
					game.goToGameOrMenu(true);
					if (getSharedPreferences(SP_PREFS_NAME, 0).getBoolean(
							SP_USE_VIBRO, true))
						getEngine().vibrate(1000);
				}
				restartLayout.setVisibility(View.GONE);
			}
		});

		Button btnMenu = (Button) restartLayout.findViewById(R.id.menuBtn);
		btnMenu.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				restartLayout.setVisibility(View.GONE);
				onGameResumed();
				game.goToGameOrMenu(false);
			}
		});

		Button btnSave = (Button) findViewById(R.id.settSaveBtn);
		btnSave.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				saveGameSetting();
			}
		});

		Button btnScoreClose = (Button) findViewById(R.id.scoreCloseButton);
		btnScoreClose.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				findViewById(R.id.scoreRankDialog).setVisibility(View.GONE);
			}
		});

		Button btnSettingClose = (Button) findViewById(R.id.settCloseBtn);
		btnSettingClose.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				findViewById(R.id.settingsDialog).setVisibility(View.GONE);
			}
		});

		Button btnExit = (Button) findViewById(R.id.backExitButton);
		btnExit.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				finish();
			}
		});

		Button btnMenuResume = (Button) findViewById(R.id.backMenuResumeButton);
		btnMenuResume.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				findViewById(R.id.backMenuDialog).setVisibility(View.GONE);
			}
		});

		Button btnBackMenu = (Button) findViewById(R.id.backMenuButton);
		btnBackMenu.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				game.goToGameOrMenu(false);
				findViewById(R.id.backMenuDialog).setVisibility(View.GONE);
			}
		});

		Button btnBackResume = (Button) findViewById(R.id.backResumeButton);
		btnBackResume.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				game.unPauseGame();
				findViewById(R.id.backMenuDialog).setVisibility(View.GONE);
			}
		});

		final Button btnUpdateScore = (Button) findViewById(R.id.scoreUpdateButton);
		btnUpdateScore.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				btnUpdateScore.setEnabled(false);
				gameScore.updateScores(true);
				btnUpdateScore.setEnabled(true);
			}
		});

	}

	private void saveGameSetting() {
		this.findViewById(R.id.settingsDialog).setVisibility(View.GONE);

		SharedPreferences settings = getSharedPreferences(SP_PREFS_NAME, 0);
		SharedPreferences.Editor editor = settings.edit();

		boolean useSound = ((CheckBox) findViewById(R.id.settSoundEnable))
				.isChecked();
		boolean useVibro = ((CheckBox) findViewById(R.id.settVibroEnable))
				.isChecked();

		editor.putBoolean(SP_USE_SOUND, useSound);
		editor.putBoolean(SP_USE_VIBRO, useVibro);

		if (useSound) {
			if (!music.isPlaying()) {
				music.play();
			}
		} else {
			if (music.isPlaying())
				music.pause();
		}
		// Commit the edits!
		editor.commit();
	}

	@Override
	public Engine onLoadEngine() {
		Log.d(" xx ", "onLoadEngine() ...");
		this.initScreenSize();
		Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
		RatioResolutionPolicy resolutionPolicy = new RatioResolutionPolicy(
				WIDTH, HEIGHT);
		EngineOptions engineOptions = new EngineOptions(true,
				ScreenOrientation.LANDSCAPE, resolutionPolicy, camera);
		return new Engine(engineOptions.setNeedsSound(true).setNeedsMusic(true));
	}

	private void initScreenSize() {
		Display display = getWindowManager().getDefaultDisplay();
		WIDTH = display.getWidth();
		HEIGHT = display.getHeight();
		if (WIDTH <= 480 && HEIGHT <= 320) {
			WIDTH = 480;
			HEIGHT = 320;
		}
		Log.i("WIDTH x HEIGHT", WIDTH + " x " + HEIGHT);
	}

	@Override
	public void onLoadResources() {
		Log.d(" xx ", "onLoadResources() ...");
		this.loadImages(getPicSizeFromScrWidth(WIDTH));
		this.loadFonts();
		this.loadSounds();
	}

	private int getPicSizeFromScrWidth(int scrWidth) {
		if (scrWidth <= 480) {
			return 480; // 480*320
		} else if (scrWidth > 480 && scrWidth <= 800) {
			return 800; // 800*480
		} else if (scrWidth > 800 && scrWidth <= 854) {
			return 854;// 854*480
		} else if (scrWidth > 854 && scrWidth <= 960) {
			return 960;// 960*540
		} else if (scrWidth > 960 && scrWidth <= 1280) {
			return 1280;// 1280*720
		}
		return 800;
	}

	/**
	 * 
	 * @param psize
	 *            : screen height pixel size
	 */
	private void loadImages(int psize) {
		Texture mTexture = new Texture(1024, 1024, TextureOptions.DEFAULT);
		TextureRegionFactory.setAssetBasePath("graphics/" + psize + "/");
		hills = TextureRegionFactory.createFromAsset(mTexture, this,
				"backgroundHills.png", 0, 0);
		sky = TextureRegionFactory.createFromAsset(mTexture, this,
				"backgroundSky.png", 0, 306);
		grass = TextureRegionFactory.createFromAsset(mTexture, this,
				"backgroundGrass.png", 0, 642);
		barrel = TextureRegionFactory.createFromAsset(mTexture, this,
				"barrel.png", 802, 0);
		aim = TextureRegionFactory.createFromAsset(mTexture, this,
				"crosshairs.png", 802, 352);
		duckFly = TextureRegionFactory.createTiledFromAsset(mTexture, this,
				"duckallframes.png", 0, 642 + 82, 4, 4);
		duckFlyFlipped = duckFly.clone();
		duckFlyFlipped.setFlippedHorizontal(true);
		shell = TextureRegionFactory.createFromAsset(mTexture, this,
				"shell.png", 322, 642 + 82);
		pauseButton = TextureRegionFactory.createFromAsset(mTexture, this,
				"pause.png", 322 + 50, 642 + 82);
		feather = TextureRegionFactory.createFromAsset(mTexture, this,
				"feather.png", 0, 642 + 82 + 256);
		featherFlipped = feather.clone();
		featherFlipped.setFlippedHorizontal(true);
		this.mEngine.getTextureManager().loadTexture(mTexture);

		// no enough space in mTexture left :)
		Texture mTexture2 = new Texture(1024, 1024, TextureOptions.DEFAULT);
		largeCloud = TextureRegionFactory.createFromAsset(mTexture2, this,
				"largecloud.png", 0, 0);
		mediumCloud = TextureRegionFactory.createFromAsset(mTexture2, this,
				"mediumcloud.png", 242, 0);
		smallCloud = TextureRegionFactory.createFromAsset(mTexture2, this,
				"smallcloud.png", 242 + 130, 0);
		flash = TextureRegionFactory.createFromAsset(mTexture2, this,
				"muzzleflash.png", 0, 66);
		shot = TextureRegionFactory.createFromAsset(mTexture2, this,
				"shot.png", 98, 66);
		this.mEngine.getTextureManager().loadTexture(mTexture2);

		Texture mTexture3 = new Texture(1024, 1024, TextureOptions.DEFAULT);
		logo = TextureRegionFactory.createFromAsset(mTexture3, this,
				"title.png", 0, 0);

		String language = String
				.format("%s", Locale.getDefault().getLanguage());
		if ("zh".equalsIgnoreCase(language)) {// Chinese
			startButton = TextureRegionFactory.createFromAsset(mTexture3, this,
					"startbutton_zh.png", 0, 226);
			settingsButton = TextureRegionFactory.createFromAsset(mTexture3,
					this, "settingsbutton_zh.png", 0, 226 + 50);
			scoresButton = TextureRegionFactory.createFromAsset(mTexture3,
					this, "scoresbutton_zh.png", 0, 226 + 50 + 50);
		} else {// default English
			startButton = TextureRegionFactory.createFromAsset(mTexture3, this,
					"startbutton.png", 0, 226);
			settingsButton = TextureRegionFactory.createFromAsset(mTexture3,
					this, "settingsbutton.png", 0, 226 + 50);
			scoresButton = TextureRegionFactory.createFromAsset(mTexture3,
					this, "scoresbutton.png", 0, 226 + 50 + 50);
		}
		this.mEngine.getTextureManager().loadTexture(mTexture3);
	}

	private void loadFonts() {
		fontTexture = new Texture(256, 256, TextureOptions.DEFAULT);
		FontFactory.setAssetBasePath("font/");
		font = FontFactory.createFromAsset(fontTexture, this, "comixheavy.ttf",
				25, true, Color.BLACK);
		this.mEngine.getTextureManager().loadTexture(fontTexture);
		this.mEngine.getFontManager().loadFont(font);
	}

	private void loadSounds() {
		SoundFactory.setAssetBasePath("sounds/");
		MusicFactory.setAssetBasePath("sounds/");
		try {
			sGroundHit = SoundFactory.createSoundFromAsset(
					this.mEngine.getSoundManager(), this, "duckgroundhit.ogg");
			sDuckQuack = SoundFactory.createSoundFromAsset(
					this.mEngine.getSoundManager(), this, "duckquack.ogg");
			sShotReload = SoundFactory.createSoundFromAsset(
					this.mEngine.getSoundManager(), this, "gunshotreload.ogg");
			music = MusicFactory.createMusicFromAsset(
					this.mEngine.getMusicManager(), this,
					"background_country_ambience_loop.ogg");
		} catch (final IOException e) {
			Debug.e("Error", e);
		}
	}

	@Override
	public void onLoadComplete() {
		Log.d(" xx ", "onLoadComplete() ...");
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		Log.d(" xx ", "onKeyDown() ...");
		if (game != null) {
			return game.onKeyDown(keyCode);
		}
		return true;
	}

	@Override
	public Scene onLoadScene() {
		Log.d(" xx ", "onLoadScene() ...");
		// this.mEngine.registerUpdateHandler(new FPSLogger(){
		// @Override
		// protected void onHandleAverageDurationElapsed(float pFPS) {
		// super.onHandleAverageDurationElapsed(pFPS);
		//
		// }
		// });

		final Scene scene = new Scene(3);
		game = new Game(scene, this);
		scene.registerUpdateHandler(new IUpdateHandler() {
			public void onUpdate(float secondsElapsed) {
				game.update();
			}
			public void reset() {
			}
		});
		// enable accelerometer
		this.mEngine.enableAccelerometerSensor(this, this);
		this.mEngine.enableVibrator(this);
		scene.setOnSceneTouchListener(new IOnSceneTouchListener() {
			public boolean onSceneTouchEvent(Scene scene,
					TouchEvent sceneTouchEvent) {
				game.onTouch(sceneTouchEvent);
				return true;
			}
		});
		return scene;
	}

	@Override
	public void onAccelerometerChanged(AccelerometerData accelerometerData) {
//		if (game != null) {
//			game.onAccelerometerChanged(accelerometerData);
//		}
	}

	@Override
	protected int getLayoutID() {
		Log.d(" xx ", "getLayoutID() ...");
		return R.layout.main;
	}

	@Override
	protected int getRenderSurfaceViewID() {
		Log.d(" xx ", "getRenderSurfaceViewID() ...");
		return R.id.andengine_surface;
	}

	@Override
	protected void onPause() {
		Log.d(" xx ", "onPause() ...");
		// TODO Auto-generated method stub
		super.onPause();
		if (music != null) {
			SharedPreferences settings = getSharedPreferences(SP_PREFS_NAME, 0);
			if (settings.getBoolean(SP_USE_SOUND, true)) {
				music.pause();
				musicPaused = true;
			}
		}
		if (game != null) {
			if (game.getGAME_STATE() == Game.STATE_RUN) {
				game.pauseGame();
			}
		}
	}

	@Override
	protected void onResume() {
		Log.d(" xx ", "onResume() ...");
		super.onResume();
		if (music != null && musicPaused) {
			music.resume();
			musicPaused = false;
		}
		if (game != null) {
			game.setLoadComplete(false);
			if (game.isPaused()) {
				game.unPauseGame();
			}
		}
		this.hideLoadimg(false);
	}

	public void hideLoadimg(final boolean hideLoadimg) {
		runOnUiThread(new Thread() {
			@Override
			public void run() {
				findViewById(R.id.loadingImage).setVisibility(
						hideLoadimg ? View.GONE : View.VISIBLE);
			}
		});
	}
}